﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Lz.HttpDemo.Http
{
    /// <summary>
    ///  Http 请求类 
    /// </summary>
    public class HttpClientService
    {

        /// <summary>
        /// 请求
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        static Stream Request(HttpClientContent param)
        {
            var encoding = param.Encode;
            byte[] data = encoding.GetBytes(param.Data);
            var request = WebRequest.Create(param.Url) as HttpWebRequest;
            request.Method = param.MethodType.ToString();
            request.ContentType = param.ContentType;
            if (param.Headers != null && param.Headers.Count > 0)
            {
                foreach (var item in param.Headers)
                {
                    request.Headers.Add(item.Key, item.Value);
                }
            }
            if (param.X509Certificate != null && param.X509Certificate.Count > 0)
            {
                request.ClientCertificates.AddRange(param.X509Certificate.ToArray());
            }
            if (param.MethodType == HttpMethodType.Post || param.MethodType == HttpMethodType.Put)
            {
                request.ContentLength = data.Length;
                using (var outstream = request.GetRequestStream())
                {
                    outstream.Write(data, 0, data.Length);
                }
            }
            var response = request.GetResponse() as HttpWebResponse;
            return response.GetResponseStream();
        }

        #region Get请求

        /// <summary>
        /// Get请求
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public static Stream GetRequest(HttpClientContent param)
        {
            param.MethodType = HttpMethodType.Get;
            return Request(param);
        }

        /// <summary>
        /// Get请求
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public static Stream GetStream(HttpClientContent param)
        {
            return GetRequest(param);
        }


        /// <summary>
        /// Get请求
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public static string GetString(HttpClientContent param)
        {
            try
            {
                using (var s = new StreamReader(GetRequest(param), Encoding.UTF8))
                {
                    return s.ReadToEnd();
                }

            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }


        #endregion

        #region Post请求

        /// <summary>
        /// Post请求
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public static Stream PostRequest(HttpClientContent param)
        {
            param.MethodType = HttpMethodType.Post;
            return Request(param);
        }

        /// <summary>
        /// Post 请求
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public static Stream PostStream(HttpClientContent param)
        {
            return Request(param);
        }

        /// <summary>
        /// Post 请求
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public static string PostString(HttpClientContent param)
        {
            try
            {
                using (var s = new StreamReader(PostRequest(param), Encoding.UTF8))
                {
                    return s.ReadToEnd();
                }
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        #endregion

        #region 上传文件
        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public static string UploadFile(HttpClientUpload param)
        {
            var rq = (HttpWebRequest)WebRequest.Create(param.Url);
            rq.Method = "POST";
            //rq.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36";
            var fileMemoryStream = new MemoryStream(); //文件写入流
            string boundary = "---------------------" + DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo);
            rq.ContentType = $"multipart/form-data; boundary={boundary}";

            if (param.Files != null && param.Files.Count > 0)
            {
                param.Files.ForEach(files =>
                {

                    var postStream = new MemoryStream();
                    //读取文件流
                    if (string.IsNullOrWhiteSpace(files.FileName))
                    {
                        files.FileName = Path.GetFileName(files.FilePath);
                    }

                    var fileStream = new FileStream(files.FilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);

                    StringBuilder fileFormdataTemplate = new StringBuilder();
                    fileFormdataTemplate.Append("--" + boundary + "\r\n");
                    fileFormdataTemplate.Append("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n");
                    fileFormdataTemplate.Append("Content-Type: application/octet-stream\r\n\r\n");

                    var formHeader = string.Format(fileFormdataTemplate.ToString(), files.Name, files.FileName);

                    //头部边界线
                    var formHeaderBytes = Encoding.UTF8.GetBytes(formHeader);

                    //写入头部边界线
                    postStream.Write(formHeaderBytes, 0, formHeaderBytes.Length);

                    //写入文件内存流
                    if (fileStream != null)
                    {
                        byte[] fileBuffer = new byte[1024];
                        int filebytesRead = 0;
                        while ((filebytesRead = fileStream.Read(fileBuffer, 0, fileBuffer.Length)) != 0)
                        {
                            postStream.Write(fileBuffer, 0, filebytesRead);
                        }
                    }

                    //文件换行
                    var fileLine = Encoding.UTF8.GetBytes("\r\n");
                    postStream.Write(fileLine, 0, fileLine.Length);

                    //写入到总流
                    fileMemoryStream.Write(postStream.ToArray(), 0, postStream.ToArray().Length);

                    postStream.Close();
                    postStream.Dispose();
                });
            }

            //边界线
            var footer = Encoding.ASCII.GetBytes("--" + boundary + "--\r\n");
            fileMemoryStream.Write(footer, 0, footer.Length);

            var data = fileMemoryStream.ToArray();
            rq.ContentLength = data.Length;

            //写入流
            using (Stream requestStream = rq.GetRequestStream())
            {
                requestStream.Write(data, 0, data.Length);
            }
            var response = (HttpWebResponse)rq.GetResponse();
            using (var responseStream = response.GetResponseStream())
            {
                using (var myStreamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8")))
                {
                    return myStreamReader.ReadToEnd();
                }
            }
        }
        #endregion
    }
}
